package controllers;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import play.libs.Json;

import com.fasterxml.jackson.databind.node.ObjectNode;

public class TableModel {
	public class AoColum {
		public class Rules {
			public boolean required = false;
			public boolean digits = false;
			public boolean number = false;
		}

		public class Messages {
			public String required = "不能为空";
			public String digits = "必须为数字";
			public String number = "必须为数字";
		}

		public class ValidationRules {
			public Rules rules = new Rules();
			public Messages messages = new Messages();
			public String validate_cssclass = "required"; 
		}

		public class EditableSetting {
			public EditableSetting() {
				type = "text";
			}

			public String type;     

		}
		
		public class ImageSetting extends EditableSetting {
			public ImageSetting() {
				type = "image";
			}
		}

		public class SelectSetting extends EditableSetting {
			public SelectSetting() {
				type = "select";
				submit = "确定";
			}

			public String data;
			public String submit;
		}

		public class DateSetting extends EditableSetting {
			public DateSetting() {
				type = "datepicker";
			}
		}
		
		public class DatetimeSetting extends EditableSetting {
			public DatetimeSetting() {
				type = "datetimepicker";
			}
		}



		public String type;
		public String editable_type;
		public String mData;
		public String sTitle;
		public ValidationRules validation_rules;
		public boolean editable;
		public EditableSetting editable_settings;
		public boolean isSearch;
		public String default_value;
		public boolean required;
		public String edit_data;
		public boolean isRangeSearch;
		public String search_type;
		public String foreign_table;
		public String foreign_field;
		public String co_table;
		public String co_primary_field_in_cotable;
		public String co_connected_fields_in_cotable;
		public String co_connected_fields_in_this;
		public boolean isQuickSearch;


		public void setValidation_rules(ValidationRules validation_rules) {
			this.validation_rules = validation_rules;
		}

		public AoColum(String mData, String sTitle, boolean required, 
				String default_value, boolean isSearch, boolean editable, String editable_type, String edit_data,
				EditableSetting editable_settings, String searchType, String foreign_table, String foreign_field,
				String cotable, String primary_field_in_cotable, String connected_fields_in_cotable, String connected_fields_in_this,
				boolean isQuickSearch
				) {
			super();
			this.editable_type = editable_type;
			this.mData = mData;
			this.sTitle = sTitle;
			this.editable = editable;
			this.editable_settings = editable_settings;
			this.isSearch = isSearch;
			this.default_value = default_value;
			this.required = required;
			this.edit_data = edit_data;
			this.search_type = searchType;
			this.foreign_table = foreign_table;
			this.foreign_field = foreign_field;
			this.co_table = cotable;
			this.co_primary_field_in_cotable = primary_field_in_cotable;
			this.co_connected_fields_in_this = connected_fields_in_this;
			this.co_connected_fields_in_cotable = connected_fields_in_cotable;
			this.isQuickSearch = isQuickSearch;
		}

		public String getEdit_data() {
			return edit_data;
		}

		public void setEdit_data(String edit_data) {
			this.edit_data = edit_data;
		}

		public boolean equals(Object other) {
			if (other instanceof String) {
				return getmData().equalsIgnoreCase(other.toString());
			} else {
				return false;
			}
		}
		public String getEditable_type() {
			return editable_type;
		}
		public void setEditable_type(String editable_type) {
			this.editable_type = editable_type;
		}

		public String getType() {
			return type;
		}
		public String getDefault_value() {
			return default_value;
		}
		public void setDefault_value(String default_value) {
			this.default_value = default_value;
		}
		public boolean getRequired() {
			return required;
		}
		public void setRequired(boolean required) {
			this.required = required;
		}
		public void setType(String type) {
			this.type = type;
		}
		public String getmData() {
			return mData;
		}
		public void setmData(String mData) {
			this.mData = mData;
		}
		public String getsTitle() {
			return sTitle;
		}
		public void setsTitle(String sTitle) {
			this.sTitle = sTitle;
		}

		public boolean getEditable() {
			return editable;
		}
		public void setEditable(boolean editable) {
			this.editable = editable;
		}
		public EditableSetting getEditable_settings() {
			return editable_settings;
		}
		public void setEditable_settings(EditableSetting editable_settings) {
			this.editable_settings = editable_settings;
		}
		public boolean getSearch() {
			return isSearch;
		}
		public void setSearch(boolean isSearch) {
			this.isSearch = isSearch;
		}


	}
	public String title;
	public String name;
	public int newFormWidth;
	public boolean showAdd;
	public boolean showSearch;
	public boolean showDelete;
	public List<AoColum> aoColums;

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getNewFormWidth() {
		return newFormWidth;
	}

	public void setNewFormWidth(int newFormWidth) {
		this.newFormWidth = newFormWidth;
	}

	public List<AoColum> getAoColums() {
		return aoColums;
	}

	public void setAoColums(List<AoColum> aoColums) {
		this.aoColums = aoColums;
	}

	public boolean getShowAdd() {
		return showAdd;
	}

	public void setShowAdd(boolean showAdd) {
		this.showAdd = showAdd;
	}

	public boolean getShowSearch() {
		return showSearch;
	}

	public void setShowSearch(boolean showSearch) {
		this.showSearch = showSearch;
	}

	public boolean getShowDelete() {
		return showDelete;
	}

	public void setShowDelete(boolean showDelete) {
		this.showDelete = showDelete;
	}

	public TableModel() {

	}

	public TableModel(Class<?> cls, int formWidth, String title,  boolean showAdd, boolean showSearch, boolean showDelete, List<AoColum> colums) {
		buildModel(cls, formWidth, title, showAdd, showSearch, showDelete, colums);
	}

	public void buildModel(Class<?> cls, int formWidth, String title, boolean showAdd, boolean showSearch, boolean showDelete, List<AoColum> colums) {
		setNewFormWidth(formWidth);
		setAoColums(colums);
		setName(cls.getSimpleName().toLowerCase());
		setTitle(title);
		setShowAdd(showAdd);
		setShowSearch(showSearch);
		setShowDelete(showDelete);

		Field[] fields = cls.getDeclaredFields();
		Map<String, Field> fieldMap = new HashMap<String, Field>();

		for (Field field : fields) {
			fieldMap.put(field.getName(), field);
		}

		for (AoColum c : getAoColums()) {
			String fieldType = "";
			Field field = fieldMap.get(c.getmData());
			if (field == null) {
				fieldType = "String";
			}  else {
				fieldType = field.getType().getSimpleName();
			}
			c.setType(fieldType);         
			assignEditableSettings(c);
			assignValidateRules(c);
		}
	}

	public void assignEditableSettings(AoColum a) {
		if (a.getEditable_type() == null) {
			a.setEditable_settings(a.new EditableSetting());
			return;
		}

		if (a.getEditable_type().equalsIgnoreCase("edit_box")) {
			a.setEditable_settings(a.new EditableSetting());
		} else if (a.getEditable_type().equalsIgnoreCase("date")) {
			a.setEditable_settings(a.new DateSetting());
		} else if (a.getEditable_type().equalsIgnoreCase("datetime")) {
			a.setEditable_settings(a.new DatetimeSetting());
		} else if (a.getEditable_type().equalsIgnoreCase("select")) {
			a.setEditable_settings(createSelectSetting(a));
		} else if (a.getEditable_type().equalsIgnoreCase("image")){
			a.setEditable_settings(a.new ImageSetting());
		} else {
			a.setEditable_settings(a.new EditableSetting());
		}
	}

	public AoColum.SelectSetting createSelectSetting(AoColum a) {
		AoColum.SelectSetting st = a.new SelectSetting();
		if (a.getEdit_data() == null) {
			ObjectNode node = Json.newObject();
			node.put(a.default_value, a.default_value);
			st.data = node.toString();
		} else {
			st.data = a.getEdit_data();
		}
		return st;
	}

	public AoColum.ValidationRules assignValidateRules(AoColum a) {
		AoColum.ValidationRules r = a.new ValidationRules();
		if (a.getRequired()) {
			r.rules.required = true;
		}

		if (a.getType().equalsIgnoreCase("int") || 
				a.getType().equalsIgnoreCase("Integer") ||
				a.getType().equalsIgnoreCase("double") ||
				a.getType().equalsIgnoreCase("Double")) {
			r.rules.number = true;
		}
		
		a.setValidation_rules(r);

		return r;
	}

}
